<?php


namespace Tools\Utils;


class DateTime
{
    /**
     * 计算出两个日期之间的月份
     * @param $start_date
     * @param $end_date
     * @param string $explode [年份和月份之间分隔符，此例为 - ]
     * @param boolean $addOne [算取完之后最后是否加一月，用于算取时间戳用]
     * @return array [type]             [返回是两个月份之间所有月份字符串]
     * @author Eric
     */
    public static function dateMonths($start_date, $end_date, $explode = '-', $addOne = false): array
    {
        //判断两个时间是不是需要调换顺序
        $start_int = strtotime($start_date);
        $end_int = strtotime($end_date);
        if ($start_int > $end_int) {
            $tmp = $start_date;
            $start_date = $end_date;
            $end_date = $tmp;
        }


        //结束时间月份+1，如果是13则为新年的一月份
        $start_arr = explode($explode, $start_date);
        $start_year = intval($start_arr[0]);
        $start_month = intval($start_arr[1]);


        $end_arr = explode($explode, $end_date);
        $end_year = intval($end_arr[0]);
        $end_month = intval($end_arr[1]);


        $data = array();
        $data[] = $start_date;


        $tmp_month = $start_month;
        $tmp_year = $start_year;


        //如果起止不相等，一直循环
        while (!(($tmp_month == $end_month) && ($tmp_year == $end_year))) {
            $tmp_month++;
            //超过十二月份，到新年的一月份
            if ($tmp_month > 12) {
                $tmp_month = 1;
                $tmp_year++;
            }
            $data[] = $tmp_year . $explode . str_pad($tmp_month, 2, '0', STR_PAD_LEFT);
        }


        if ($addOne == true) {
            $tmp_month++;
            //超过十二月份，到新年的一月份
            if ($tmp_month > 12) {
                $tmp_month = 1;
                $tmp_year++;
            }
            $data[] = $tmp_year . $explode . str_pad($tmp_month, 2, '0', STR_PAD_LEFT);
        }


        return $data;
    }

    /**
     * 求两个日期之间相差的天数
     * (针对1970年1月1日之后，求之前可以采用泰勒公式)
     * @param string $day1
     * @param string $day2
     * @return float|int
     */
    public static function diffBetweenTwoDays(string $day1, string $day2)
    {
        $second1 = strtotime($day1);
        $second2 = strtotime($day2);

        if ($second1 < $second2) {
            $tmp = $second2;
            $second2 = $second1;
            $second1 = $tmp;
        }
        return ($second1 - $second2) / 86400;
    }

    /**
     * 获取两个日期之间的所有日期 2016-04-02至2016-04-16
     */
    public static function prDates($start, $end)
    {
        $dt_start = strtotime($start);
        $dt_end = strtotime($end);
        $value = '';
        while ($dt_start <= $dt_end) {
            $value .= date('Y-m-d', $dt_start) . ",";
            $dt_start = strtotime('+1 day', $dt_start);
        }
        $d = substr($value, 0, -1);
        return explode(',', $d);
    }


    public static function getNextMonthDays($date)
    {
        $timestamp = strtotime($date);
        $arr = getdate($timestamp);
        if ($arr['mon'] == 12) {
            $year = $arr['year'] + 1;
            $month = $arr['mon'] - 11;
            $firstday = $year . '-0' . $month . '-01';
        } else {
            $firstday = date('Y-m-01', strtotime(date('Y', $timestamp) . '-' . (date('m', $timestamp) + 1) . '-01'));
        }
        return date('Y-m-d', strtotime("$firstday +1 month -1 day"));
    }


    public static function getlastMonthDays($date)
    {
        $timestamp = strtotime($date);
        $firstday = date('Y-m-01', strtotime(date('Y', $timestamp) . '-' . (date('m', $timestamp) - 1) . '-01'));
        return date('Y-m-d', strtotime("$firstday +1 month -1 day"));
    }


    //格式化友好显示时间
    public static function formatTime($time)
    {

        if (!is_int($time)) {
            $time = strtotime($time);
        }

        $now = time();
        $day = date('Y-m-d', $time);
        $today = date('Y-m-d');

        $dayArr = explode('-', $day);
        $todayArr = explode('-', $today);

        //距离的天数，这种方法超过30天则不一定准确，但是30天内是准确的，因为一个月可能是30天也可能是31天
        $days = ($todayArr[0] - $dayArr[0]) * 365 + (($todayArr[1] - $dayArr[1]) * 30) + ($todayArr[2] - $dayArr[2]);
        //距离的秒数
        $secs = $now - $time;
        $secs = $secs >= 1 ? $secs : 1;

        if ($todayArr[0] - $dayArr[0] > 0 && $days > 3) {//跨年且超过3天
            return date('Y-m-d', $time);
        } else {

            if ($days < 1) {//今天
                if ($secs < 60) {
                    return $secs . '秒前';
                } elseif ($secs < 3600) {
                    return floor($secs / 60) . "分钟前";
                } else {
                    return floor($secs / 3600) . "小时前";
                }
            } else if ($days < 2) {//昨天
                $hour = date('H', $time);

                return "昨天" . $hour . '点';
            } elseif ($days < 3) {//前天
                $hour = date('H', $time);

                return "前天" . $hour . '点';
            } else {//三天前
                return date('m月d号', $time);
            }
        }
    }

    /**
     * 时间戳人性化转化
     * @param $time
     * @return string
     */
    public static function time_tran($time): string
    {
        $t = time() - $time;
        $f = array(
            '31536000' => '年',
            '2592000' => '个月',
            '604800' => '星期',
            '86400' => '天',
            '3600' => '小时',
            '60' => '分钟',
            '1' => '秒'
        );
        foreach ($f as $k => $v) {
            if (0 != $c = floor($t / (int)$k)) {
                return $c . $v . '前';
            }
        }
        return "";
    }

    /**
     * 获取毫秒数
     * @return float
     */
    public static function msectime(): float
    {
        list($msec, $sec) = explode(' ', microtime());
        return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
    }

    public static function getWeekDay(): string
    {
        $weekarray = array("日", "一", "二", "三", "四", "五", "六"); //先定义一个数组
        return "星期" . $weekarray[date("w")];
    }

    /**
     * 区间计算式
     * $sections array  ['$min:$max:$val'], e.g.:['0:50:10', '50:70:15', '70:90:20', '90:100:25']
     */
    public static function sec_exp($var, array $sections)
    {

        if (empty($sections)) {
            return FALSE;
        }
        $sec = array_shift($sections);
        list($min, $max, $val) = explode(':', $sec);

        return ($var > $min && $var <= $max) ? $val : sec_exp($var, $sections);
    }

}
